﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight.Ioc;
using JiveMessenger.Models;
using System.Linq;
using JmShared;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Threading;
using System.IO;
using System.Xml;
using System.Windows.Input;
using System.Diagnostics;
using System.Collections.Specialized;
using JiveMessenger.User;
using System.Windows;
using System.Text.RegularExpressions;
using JiveMessenger.Utilities;
using System.Security;
using Windows.Security.Authentication.OnlineId;
using System.Threading.Tasks;
using GalaSoft.MvvmLight.Views;
using Newtonsoft.Json.Linq;
using System.Net.Http;
using GalaSoft.MvvmLight.Threading;

namespace JiveMessenger.ViewModels
{
    public class ViewModelLoginControl : ViewModelBaseEx, IViewModelLoginControl
    {
        private IClient _currentClient;
        private object LockObject = new object();

        public RelayCommand LoginWithMicrosoftCommand { get; set; }
        public RelayCommand LoginCommand { get; private set; }
        public RelayCommand ResetPasswordCommand { get; private set; }
        public RelayCommand RegisterUserCommand { get; private set; }
        public RelayCommand ShowServerPickerCommand { get; set; }
        public RelayCommand CloseAddServerPopupCommand { get; set; }
        public RelayCommand RemoveServerCommand { get; private set; }
        public RelayCommand<string> AddServerCommand { get; private set; }

        //private string _username;
        //public string Username
        //{
        //    get { return _username; }
        //    set
        //    {
        //        if (_username != value)
        //        {
        //            Set(() => Username, ref _username, value);
        //        }
        //    }
        //}


        private string _password;
        public string Password
        {
            get { return _password; }
            set
            {
                if (_password != value)
                {
                    Set(() => Password, ref _password, value);
                }
            }
        }


        private string _loginControlStatusText;
        public string LoginControlStatusText
        {
            get { return _loginControlStatusText; }
            set
            {
                if (_loginControlStatusText != value)
                {
                    Set(() => LoginControlStatusText, ref _loginControlStatusText, value);
                }
            }
        }

        private bool _isLoginButtonEnabled;
        public bool IsLoginButtonEnabled
        {
            get { return _isLoginButtonEnabled; }
            set
            {
                if (_isLoginButtonEnabled != value)
                {
                    Set(() => IsLoginButtonEnabled, ref _isLoginButtonEnabled, value);
                }
            }
        }

        private bool _isServerPickerVisible;
        public bool IsServerPickerVisible
        {
            get { return _isServerPickerVisible; }
            set
            {
                if (_isServerPickerVisible != value)
                {
                    Set(() => IsServerPickerVisible, ref _isServerPickerVisible, value);
                }
            }
        }

        private bool _isAddServerPopupOpen;
        public bool IsAddServerPopupOpen
        {
            get { return _isAddServerPopupOpen; }
            set
            {
                if (_isAddServerPopupOpen != value)
                {
                    Set(() => IsAddServerPopupOpen, ref _isAddServerPopupOpen, value);
                }
            }
        }
        //private bool _isAddServerPopupOpen;
        //public bool IsAddServerPopupOpen
        //{
        //    get { return _isAddServerPopupOpen; }
        //    set
        //    {
        //        if (_isAddServerPopupOpen != value)
        //        {
        //            _isAddServerPopupOpen = value;

        //            RaisePropertyChanged("IsAddServerPopupOpen");
        //        }
        //    }
        //}
        public ViewModelLoginControl() : base() { }
        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public ViewModelLoginControl(IClient currentClient)
        {

            if (IsInDesignMode)
            {
                // Code runs in Blend --> create design time data.
                // this.Password = new SecureString();

            }
            else
            {
                _currentClient = currentClient;

                //this.Username = AppSettings.Instance.UsernameSetting;
                //Task.Run(() =>
                //{
                this.Password = CredentialsManager.GetStoredPasswordForUser(AppSettings.Instance.UsernameSetting);
                //});

                IsLoginButtonEnabled = true;

                RegisterUserCommand = new RelayCommand(RegisterUserCommandAction);
                ResetPasswordCommand = new RelayCommand(ResetPasswordCommandAction);
                LoginCommand = new RelayCommand(LoginCommandAction);
                LoginWithMicrosoftCommand = new RelayCommand(LoginWithMicrosoftCommandAction);
                ShowServerPickerCommand = new RelayCommand(ShowServerPickerCommandAction);
                RemoveServerCommand = new RelayCommand(RemoveServerCommandAction);
                AddServerCommand = new RelayCommand<string>(AddServerCommandAction);
                CloseAddServerPopupCommand = new RelayCommand(CloseAddServerPopupCommandAction);
            }
            if (string.IsNullOrEmpty(AppSettings.Instance.ServerSetting))
            {
                IsServerPickerVisible = true;
            }
            Messenger.Default.Register<NotificationMessage<string>>(this, msg =>
            {
                switch (msg.Notification)
                {
                    case "SetLoginStatusText":
                        {
                            DispatcherHelper.CheckBeginInvokeOnUI(() => this.LoginControlStatusText = msg.Content);
                            break;
                        }
                }
            });
        }

        public AppSettings AppSettings
        {
            get
            {
                return AppSettings.Instance;
            }
        }
        public async void Logout()
        {
            _currentClient.StopReconnectRetrying = true;
            await _currentClient.Connection.Logout();
            CredentialsManager.RemoveCredential(AppSettings.Instance.UsernameSetting);
            AppSettings.Instance.UsernameSetting = "";
            Password = "";


        }
        private void CloseAddServerPopupCommandAction()
        {
            IsAddServerPopupOpen = false;
        }


        private void AddServerCommandAction(string str)
        {
            if (!string.IsNullOrEmpty(str))
            {
                List<string> serverListCopy = new List<string>(AppSettings.Instance.ServerListSetting);
                serverListCopy.Add(str);
                AppSettings.Instance.ServerListSetting = serverListCopy;
                AppSettings.Instance.ServerSetting = str;
            }
            IsAddServerPopupOpen = false;
            IsServerPickerVisible = false;
        }

        private void RemoveServerCommandAction()
        {
            if (String.IsNullOrEmpty(AppSettings.Instance.ServerSetting))
                return;
            //if (MessageBox.Show("Are you sure?", string.Format("Delete {0}", this.AppSettings.ServerSetting), MessageBoxButton.OKCancel) == MessageBoxResult.OK)

            Messenger.Default.Send(new NotificationMessageAction<bool>(this, new JiveDialogQuery("Remove server?", string.Format("{0} will be deleted", AppSettings.Instance.ServerSetting)), "QueryDialog", (result) =>
            {
                if (result == true)
                {
                    List<string> serverListCopy = new List<string>(AppSettings.Instance.ServerListSetting);
                    serverListCopy.Remove(AppSettings.Instance.ServerSetting);
                    AppSettings.Instance.ServerListSetting = serverListCopy;
                    AppSettings.Instance.ServerSetting = serverListCopy.Count > 0 ? serverListCopy[0] : null;
                }
            }));
        }
        private void ShowServerPickerCommandAction()
        {
            IsServerPickerVisible = true;
        }

        private async void LoginWithMicrosoftCommandAction()
        {
            OnlineIdAuthenticator onlineIdAuthenticator = new OnlineIdAuthenticator();
            OnlineIdServiceTicketRequest serviceTicketRequest = new OnlineIdServiceTicketRequest("wl.basic", "DELEGATION");
            UserIdentity result = await onlineIdAuthenticator.AuthenticateUserAsync(serviceTicketRequest);
            if (result != null && result.Tickets[0].Value != string.Empty)
            {
                string foo = result.Tickets[0].Value;
                // Safe Customer ID
                string username = await GetUserName(foo);
                string id = result.SafeCustomerId;

            }

            else
            {

                LoginControlStatusText = "Error: Unable to get a ticket";
                Log.LogManager.GetCurrentClassLogger().Error("Unable to get a ticket: " + result.Tickets[0].ErrorCode.ToString());
                //result.Tickets[0].ErrorCode.ToString();

            }
        }
        private const string LiveApiMeUri = "https://apis.live.net/v5.0/me?access_token=";

        internal static async Task<string> GetUserName(string accessToken)
        {
            if (accessToken != null)
            {
                var uri = new Uri(LiveApiMeUri + accessToken);
                var client = new HttpClient();
                var result = await client.GetAsync(uri);
                string jsonUserInfo = await result.Content.ReadAsStringAsync();
                if (jsonUserInfo != null)
                {
                    var json = JObject.Parse(jsonUserInfo);
                    return json["name"].ToString();
                }
            }
            return string.Empty;
        }
        private void LoginCommandAction()
        {
            string password = CredentialsManager.GetStoredPasswordForUser(AppSettings.Instance.UsernameSetting);
            if (this.Password != null && this.Password != password)
            {
                CredentialsManager.RemoveCredential(AppSettings.Instance.UsernameSetting);
                CredentialsManager.SaveCredential(AppSettings.Instance.UsernameSetting, this.Password);
            }

            Match m = Regex.Match(AppSettings.Instance.UsernameSetting, @"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
            if (m.Success)
            {
                _currentClient.StopReconnectTask();
                _currentClient.IsUserConnecting = true;
                _currentClient.StartConnectTask(false);
                _currentClient.Connection.LoginResponseReceived += Connection_LoginResponseReceived;
            }
            else
            {
                this.LoginControlStatusText = "Your Email Address is invalid";
                IsLoginButtonEnabled = true;
            }
        }

        void Connection_LoginResponseReceived(object sender, Network.LoginResponseEventArgs e)
        {
            _currentClient.Connection.LoginResponseReceived -= Connection_LoginResponseReceived;
           DispatcherHelper.RunAsync(() =>
                {
                    if (e.LoginResponse.Success == true)
                    {
                        Messenger.Default.Send(new NotificationMessage(this, "NavigateToMainPage"));//_navigationService.NavigateTo("MainPage");

                    }
                    else
                        LoginControlStatusText = e.LoginResponse.Error;
                });
        }

        private void ResetPasswordCommandAction()
        {
            try
            {
                Messenger.Default.Send(new NotificationMessage(this, "OpenResetPasswordWindow"));
            }
            catch (Exception err)
            {
                Messenger.Default.Send(String.Format("Error opening url. \n {0})", err.Message));
            }
        }

        private void RegisterUserCommandAction()
        {
            try
            {
                Messenger.Default.Send(new NotificationMessage(this, "OpenRegisterWindow"));
            }
            catch (Exception err)
            {
                Messenger.Default.Send(String.Format("Error opening url. \n {0})", err.Message));
            }
        }

        public override void Cleanup()
        {
            SimpleIoc.Default.Unregister<ViewModelLoginControl>(VmHelper.Locator.ViewModelLoginControlKey);
            VmHelper.Locator.ViewModelLoginControlKey = System.Guid.NewGuid().ToString();
            base.Cleanup();
        }
        public void RunOnNetworkConnect()
        {
            this.IsLoginButtonEnabled = true;
            this.LoginControlStatusText = string.Empty;
            _currentClient.StopReconnectRetrying = false;
        }

        public void RunOnNetworkDisconnect()
        {
            this.IsLoginButtonEnabled = true;
        }
    }
}